package cn.openea.perpartner.componet.util;

import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.exception.CosServiceException;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.UploadResult;
import com.qcloud.cos.transfer.TransferManager;
import com.qcloud.cos.transfer.Upload;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

/**
 * @Name: 上传指定附件到COS中的API方法类
 * @desc:
 * @author: Mr.Yun
 * @Created: 2022/8/26 22:56
 */
@Service
@Slf4j
public class CosUpload {
    @Autowired
    private TransferManager transferManager;
    @Value("${tencent.cos.region}")
    private String region;
    @Value("${tencent.cos.bucket}")
    private String bucket;
    @Value("${tencent.cos.sysidpath}")
    private String sysidpath;

    /**
     * 上传附件到COS中-以本地File方式
     * @param uploadfile 需要上传的本地文件
     * @param isAppendName 上传到COS时，是否使用追加随机字符减少同名文件在COS上被覆盖，false表示不处理，true表示在文件名后追加5个随机字符
     * @return 如果返回地址不为空，表示上传成功
     */
    public String uploadFile(File uploadfile, boolean isAppendName) {
        return uploadFilebase(uploadfile, null, uploadfile.getName(), isAppendName);
    }

    /**
     * 上传附件到COS中-以InputStream文件流方式
     * @param inputStream 需要上传的文件流
     * @param fileName 上传文件时使用的文件名
     * @param isAppendName 上传到COS时，是否使用追加随机字符减少同名文件在COS上被覆盖，false表示不处理，true表示在文件名后追加5个随机字符
     * @return
     */
    public String uploadFile(InputStream inputStream, String fileName, boolean isAppendName){
        return uploadFilebase(null, inputStream, fileName, isAppendName);
    }

    /**
     * 上传附件到COS中的基函数
     * @param uploadfile 需要上传的本地文件，与inputStream不同时存在
     * @param inputStream 需要上传的文件流，与uploadfile不同时存在
     * @param fileName 上传文件时使用的文件名
     * @param isAppendName 上传到COS时，是否使用追加随机字符减少同名文件在COS上被覆盖，false表示不处理，true表示在文件名后追加5个随机字符
     * @return
     */
    private String uploadFilebase(File uploadfile, InputStream inputStream, String fileName, boolean isAppendName) {
        // 获取今天日期(yyyyMM)
        Date date = new Date();
        SimpleDateFormat sft = new SimpleDateFormat("yyyyMM");
        String today = sft.format(date);
        // 文件夹名称
        String folderName = sysidpath +  today + "/FILE/";
        log.debug("获取文件夹folderName=" + folderName);

        // 如果要重新在原文件名后追加随机字符
        if(isAppendName){
            int index = fileName.lastIndexOf(".");
            if(index > 1){
                //获取后辍名 如.jpg/.doc等
                String fileSuffix = fileName.substring(index);
                //获取文件名
                fileName = fileName.substring(0, index);
                // 获取随机五位数
                String suffix = randomLetter(5);
                // 防止文件重复发生覆盖,需要在文件名称增加后缀
                fileName = fileName + suffix + fileSuffix;
            }
        }
        log.debug("获取上传的文件名称upload_fileName=" + fileName);

        // 对象在存储桶中的唯一标识。
        String uploadkey = folderName + fileName;
        log.debug("对象在存储桶中的唯一标识key=" + uploadkey);

        // 指定文件将要存放的存储桶
        PutObjectRequest putObjectRequest = null;
        if(uploadfile != null){
            putObjectRequest = new PutObjectRequest(bucket, uploadkey, uploadfile);
        } else if(inputStream != null){
            putObjectRequest = new PutObjectRequest(bucket, uploadkey, inputStream, null);
        }
        try {
            // 高级接口会返回一个异步结果Upload
            // 可同步地调用 waitForUploadResult 方法等待上传完成，成功返回UploadResult, 失败抛出异常
            Upload upload = transferManager.upload(putObjectRequest);
            UploadResult uploadResult = upload.waitForUploadResult();
            log.debug("uploadResult="+uploadResult.toString());
            String finalkey = uploadResult.getKey();
            // 上传成功后，获取访问路径  https://dev-1308272144.cos.ap-guangzhou.myqcloud.com/
            String backUrl = "https://" + bucket + ".cos."+ region + ".myqcloud.com/" + finalkey;
            return backUrl;
        } catch (CosServiceException e) {
            e.printStackTrace();
        } catch (CosClientException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 随机生成num位字符串
     * @param num
     * @return
     */
    private String randomLetter(int num) {
        String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        StringBuilder sb = new StringBuilder(num+1);
        sb.append("_");
        int maxLength = str.length();
        for(int i=0; i<num; i++){
            char ch = str.charAt(new Random().nextInt(maxLength));
            sb.append(ch);
        }
        return sb.toString();
    }
}
